package com.wf.redis;

import java.util.UUID;
import java.util.concurrent.TimeUnit;


import org.apache.commons.lang3.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;

/**
 * 分布式锁实现类
 * @Author: fei.wu
 * @Email: fei.wu@rograndec.com
 * @CreateDate: 2018/8/14
 * @Version: 1.0
 */
public class RedisDistributedLock {


    private static final String LOCK_OK              = "OK";
    private static final String SET_IF_NOT_EXIST     = "NX";
    private static final String SET_WITH_EXPIRE_TIME = "PX";

    /**
     * 获得锁
     *
     * @param lockName       锁name
     * @param timeout        超时时间
     * @param acquireTimeout 获取锁的超时时间
     * @return
     */
    public String lock(String lockName, int acquireTimeout, int timeout, TimeUnit unit) throws Exception {
        Jedis jedis = RedisManager.getJedis();

        String lockKey = RedisKey.generate("redis", "lock", lockName);

        String lockId = UUID.randomUUID().toString();

        long end = System.currentTimeMillis() + unit.toMillis(acquireTimeout);
        while (System.currentTimeMillis() < end) {
            String result = jedis.set(lockKey, lockId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, unit.toMillis(timeout));
            if (LOCK_OK.equals(result)) {
                return lockId;
            }
            TimeUnit.MILLISECONDS.sleep(200);
        }

        System.out.println("获得锁超时: " + (end - System.currentTimeMillis()));

        return null;

    }


    public boolean releaseLock(String lockName, String lockId) throws Exception {
        if (StringUtils.isBlank(lockName) || lockId == null) {
            return false;
        }
        boolean releaseFlag = false;

        Jedis jedis = RedisManager.getJedis();

        String lockKey = RedisKey.generate("redis", "lock", lockName);

        while (true) {
            try {
                // 判断是不是可以释放锁
                if (lockId.equals(jedis.get(lockKey))) {
                    Long del = jedis.del(lockKey);
                    if (del == 1) {
                        releaseFlag = true;
                        break;
                    }
                    TimeUnit.MILLISECONDS.sleep(200);
                    continue;
                }
            } catch (Exception e) {
                //删除锁失败或者
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e1) {
                    Thread.currentThread().interrupt();
                }
                //长时间抛这个异常，需要人工介入。。
                e.printStackTrace();
//                logger.error("[RedisDistributedLock][releaseLock] 异常！参数: " + lockName + "\n" + e.getMessage(), e);
            }
        }

        return releaseFlag;
    }

}
